#ifndef __ROBOT_H__
#define __ROBOT_H__

#include "vec.h"
#include "parallelepiped.h"
#include "sphere.h"
#include "pyramid.h"
#include "tetrahedron.h"
#include "cylinder.h"
#include "cone.h"
//#include "utils.h"

//* ----- Type Definition -----
typedef vec3 Point3D;

struct piece{
	int contentSize;
	int nextSize;
	int tipo; // 1- Para, 2-Sphere, 3- Pyra, 4 Tetra, 5 Cone, 6 cylinder
	Shape * * content;
	piece * * next;
};

class Robot {
protected:
	//! The 4 robot's wheels
	/*!
	 *	The first wheel is the front-left one
	 *	The second wheel is the front-right one
	 *	The third wheel is the back-right one
	 *	The fourth wheel is the back-left one
	 */
	piece * wheels;

	//! The robot's base
	piece * base;

	//! The robot's arms
	/*!
	 *  Each arm is composed of one horinzontal and four vertical parallelepipeds
	 *  Each vertical segment is composed of four parallelepiped
	 */
	piece * baseArm, * secondArm, * thirdArm, * fourthArm;

	//! The robot's cylinder joints
	/*!
	 *  The baseJoint and thirdJoint are .. ones
	 *  The secondJoint is a .. one
	 */
	piece * baseJoint, * secondJoint, * thirdJoint;

	//! The robot's sphere joints
	/*!
	 *  The secondJoint and fourthJoint are .. ones
	 */
	piece * fourthJoint, * fingerJoint1, * fingerJoint2, * fingerJoint3, * fingerJoint4;
	
	//! The robot's fingers
	/*!
	 *  The hand is composed of four fingers
	 *  Each finger is composed of two segments
	 *  Each segment is composed of four parallelepipeds
	 */
	piece * finger1Segment1, * finger2Segment1, * finger3Segment1, * finger4Segment1,
		* finger1Segment2, * finger2Segment2, * finger3Segment2, * finger4Segment2;

	//! The robot's fingers tips
	piece * fingerTip1, * fingerTip2, * fingerTip3, * fingerTip4;

	//! private method to translate the piece in the X direction
	/*!
	 *  @param peca the piece to be translated
	 *  @param distance the value of the movement
	 */
	void moveX(piece * peca, double distance);

	//! private method to translate the piece in the Y direction
	/*!
	 *  @param peca the piece to be translated
	 *  @param distance the value of the movement
	 */
	void moveY(piece * peca, double distance);

	//! private method to rotate the piece in the X direction
	/*!
	 *  @param peca the piece to be translated
	 *  @param radians the value of the rotation
	 *  @param axisX the x axis
	 *  @param axisY the y axis
	 *  @param axisZ the z axis
	 */
	void rotateX(piece * peca, double radians, double axisX, double axisY, double axisZ);

	//! private method to rotate the piece in the Y direction
	/*!
	 *  @param peca the piece to be translated
	 *  @param radians the value of the rotation
	 *  @param axisX the x axis
	 *  @param axisY the y axis
	 *  @param axisZ the z axis
	 */
	void rotateY(piece * peca, double radians, double axisX, double axisY, double axisZ);

	//! private method to rotate the piece in the Z direction
	/*!
	 *  @param peca the piece to be translated
	 *  @param radians the value of the rotation
	 *  @param axisX the x axis
	 *  @param axisY the y axis
	 *  @param axisZ the z axis
	 */
	void rotateZ(piece * peca, double radians, double axisX, double axisY, double axisZ);
public:
	//! Constructor
	Robot();

	//! Move the robot left
	/*!
	 *  @param distance the value of the movement
	 */
	void moveLeft(double distance);

	//! Move the robot right
	/*!
	 *  @param distance the value of the movement
	 */
	void moveRight(double distance);

	//! Move the robot to front
	/*!
	 *  @param distance the value of the movement
	 */
	void moveFront(double distance);

	//! Move the robot to back
	/*!
	 *  @param distance the value of the movement
	 */
	void moveBack(double distance);

	//! Use the baseJoint
	/*!
	 *  @param radians the angle of the movement
	 */
	void useBaseJoint(double radians);

	//! Use the secondJoint
	/*!
	 *  @param radians the angle of the movement
	 */
	void useSecondJoint(double radians);

///----------------- GETTERS AND SETTERS -----------------

	//! Returns the private field base
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getBase();

	//! Returns the private field wheels
	/*! Used to encapsulate the field
	 */
	Sphere * * getWheels();

	//! Returns the private field baseArm
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getBaseArm();

	//! Returns the private field secondArm
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getSecondArm();

	//! Returns the private field thirdArm
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getThirdArm();

	//! Returns the private field fourthArm
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFourthArm();

	//! Returns the private field finger1segment1
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger1Segment1();

	//! Returns the private field finger2segment1
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger2Segment1();

	//! Returns the private field finger3segment1
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger3Segment1();

	//! Returns the private field finger4segment1
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger4Segment1();

	//! Returns the private field finger1segment2
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger1Segment2();

	//! Returns the private field finger2segment2
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger2Segment2();

	//! Returns the private field finger3segment2
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger3Segment2();

	//! Returns the private field finger4segment2
	/*! Used to encapsulate the field
	 */
	Parallelepiped * * getFinger4Segment2();

	//! Returns the private field baseJoint
	/*! Used to encapsulate the field
	 */
	Cylinder * * getBaseJoint();

	//! Returns the private field secondJoint
	/*! Used to encapsulate the field
	 */
	Cylinder * * getSecondJoint();

	//! Returns the private field thirdJoint
	/*! Used to encapsulate the field
	 */
	Cylinder * * getThirdJoint();

	//! Returns the private field fourthJoint
	/*! Used to encapsulate the field
	 */
	Sphere * * getFourthJoint();

	//! Returns the private field fingerJoint
	/*! Used to encapsulate the field
	 */
	Sphere * * getFingerJoint1();

	//! Returns the private field fingerJoint
	/*! Used to encapsulate the field
	 */
	Sphere * * getFingerJoint2();

	//! Returns the private field fingerJoint
	/*! Used to encapsulate the field
	 */
	Sphere * * getFingerJoint3();

	//! Returns the private field fingerJoint
	/*! Used to encapsulate the field
	 */
	Sphere * * getFingerJoint4();

	//! Returns the private field fingerTip
	/*! Used to encapsulate the field
	 */
	Pyramid * * getFingerTip1();

	//! Returns the private field fingerTip
	/*! Used to encapsulate the field
	 */
	Pyramid * * getFingerTip2();

	//! Returns the private field fingerTip
	/*! Used to encapsulate the field
	 */
	Pyramid * * getFingerTip3();

	//! Returns the private field fingerTip
	/*! Used to encapsulate the field
	 */
	Pyramid * * getFingerTip4();

	//! Returns the first piece
	piece * getFirstPiece();
};

#endif
